package model.caret;

import model.code.line.LineList;

/**
 * This is a representation of the selection in a {@link editor.code.CodePanel}.
 *
 * @author Neil Dickson
 */
public class TextCaret extends Caret {
	private LineList	lines;
	private	int			headLine;
	private	int			headCol;
	private int			tailLine;
	private	int			tailCol;
	private int			savedX;

	public static final int NONE	= Integer.MIN_VALUE;

	public TextCaret(CaretRef ref,LineList lines,int line,int col,int x) {
		this(ref,lines,line,col,line,col,x);
	}

	public TextCaret(CaretRef ref, LineList lines,int headLine, int headCol, int tailLine, int tailCol, int savedX) {
		super(ref);
		this.lines = lines;
		this.headLine = headLine;
		this.headCol = headCol;
		this.tailLine = tailLine;
		this.tailCol = tailCol;
		this.savedX = savedX;
//		if (headLine<0 || headLine>=lines.size() || tailLine<0 || tailLine>=lines.size() || headCol<0 || headCol>lines.get(headLine).length() || tailCol<0 || tailCol>lines.get(tailLine).length()) {
//			throw new RuntimeException(toString());
//		}
	}

	public void set(int line, int col) {
		set(line,col,line,col,savedX);
	}
	public void set(int line, int col, int x) {
		set(line,col,line,col,x);
	}
	public void setHead(int line,int col) {
		setHead(line,col,savedX);
	}
	public void setHead(int line,int col,int x) {
		set(line,col,tailLine,tailCol,x);
	}
	public void set(int headLine, int headCol, int tailLine, int tailCol, int savedX) {
		this.headLine = headLine;
		this.headCol = headCol;
		this.tailLine = tailLine;
		this.tailCol = tailCol;
		this.savedX = savedX;
		if (ref!=null) {
			ref.updateAll();
		}
	}

	public void set(LineList lines, int headLine, int headCol, int tailLine, int tailCol, int savedX) {
		this.lines = lines;
		set(headLine,headCol,tailLine,tailCol,savedX);
	}

	public int getHeadLine() {
		return headLine;
	}

	public int getHeadCol() {
		return headCol;
	}

	public int getTailLine() {
		return tailLine;
	}

	public int getTailCol() {
		return tailCol;
	}

	public int getSavedX() {
		return savedX;
	}

	public int getLine() {
		return getHeadLine();
	}

	public int getCol() {
		return getHeadCol();
	}

	public boolean isEmpty() {
		return headLine==tailLine && headCol==tailCol;
	}

	public int[] getSelectedRange(int line) {
		int smallerLine;
		int biggerLine;
		int smallerLineCol;
		int biggerLineCol;
		if (line>=headLine && line<=tailLine) {
			smallerLine = headLine;
			biggerLine = tailLine;
			smallerLineCol = headCol;
			biggerLineCol = tailCol;
		}
		else if (line>=tailLine && line<=headLine) {
			smallerLine = tailLine;
			biggerLine = headLine;
			smallerLineCol = tailCol;
			biggerLineCol = headCol;
		}
		else {
			// Return null to indicate that the caret does not lie anywhere on the specified line
			return null;
		}

		if (line>smallerLine) {
			if (line<biggerLine) {
				return new int[]{-1,Integer.MAX_VALUE};			// Whole line selected
			}
			else {
				return new int[]{-1,biggerLineCol};				// Line at end of selection
			}
		}
		else if (line<biggerLine) {
			return new int[]{smallerLineCol,Integer.MAX_VALUE};	// Line at beginning of selection
		}
		else {
			int smallerCol = Math.min(headCol,tailCol);
			int biggerCol = Math.max(headCol,tailCol);
			return new int[]{smallerCol,biggerCol};				// Line fully contains the selection
		}
	}
	public int getFirstLine() {
		return Math.min(headLine,tailLine);
	}
	public int getLastLine() {
		return Math.max(headLine,tailLine);
	}
	public int getFirstLineCol() {
		if (headLine>tailLine) {
			return tailCol;
		}
		else if (headLine==tailLine) {
			return Math.min(headCol,tailCol);
		}
		else {
			return headCol;
		}
	}
	public int getLastLineCol() {
		if (headLine>tailLine) {
			return headCol;
		}
		else if (headLine==tailLine) {
			return Math.max(headCol,tailCol);
		}
		else {
			return tailCol;
		}
	}

	public String toString() {
		return "TextCaret("+lines.getParent()+","+headLine+","+headCol+","+tailLine+","+tailCol+","+savedX+")";
	}

	public LineList getLineList() {
		return lines;
	}

	public boolean equals(Object o) {
		if (this==o) return true;
		if (o==null || getClass()!=o.getClass()) return false;
		TextCaret that = (TextCaret)o;
		return headCol==that.headCol && headLine==that.headLine && savedX==that.savedX && tailCol==that.tailCol && tailLine==that.tailLine && lines==that.lines;
	}
	public boolean isAfter(TextCaret that) {
		return (getFirstLine()>that.getFirstLine()) || (getFirstLine()==that.getFirstLine() && getFirstLineCol()>that.getFirstLineCol());
	}
}
